﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Models;
using Persistence;
using Models.Models;



namespace Services
{
    /// <summary>
    /// Gerencia todas as regras de negócio da entidade Cliente
    /// </summary>
    
    public class GerenciadorCliente

    {
        private IUnitOfWork unitOfWork;
        private bool shared;

        /// <summary>
        /// Construtor pode ser acessado externamente e não compartilha contexto
        /// </summary>
        public GerenciadorCliente()
        {
            this.unitOfWork = new UnitOfWork();
            shared = false;
        }

        /// <summary>
        /// Construtor acessado apenas dentro do componentes service e permite compartilhar
        /// contexto com outras classes de negócio
        /// </summary>
        /// <param name="unitOfWork"></param>
        internal GerenciadorCliente(IUnitOfWork unitOfWork)
        {
            this.unitOfWork = unitOfWork;
            shared = true;
        }

        /// <summary>
        /// Insere um novo na base de dados
        /// </summary>
        /// <param name="clienteModel">Dados do modelo</param>
        /// <returns>Chave identificante na base</returns>
        public int Inserir(Cliente clienteModel)
        {
            TB_CLIENTE clienteE = new TB_CLIENTE();
            Atribuir(clienteModel, clienteE);
            unitOfWork.RepositorioCliente.Inserir(clienteE);
            unitOfWork.Commit(shared);
            return clienteE.id_Cliente;
        }

        /// <summary>
        /// Altera dados na base de dados
        /// </summary>
        /// <param name="clienteModel"></param>
        public void Editar(Cliente clienteModel)
        {
            TB_CLIENTE clienteE = new TB_CLIENTE();
            Atribuir(clienteModel, clienteE);
            unitOfWork.RepositorioCliente.Editar(clienteE);
            unitOfWork.Commit(shared);
        }

        /// <summary>
        /// Remove da base de dados
        /// </summary>
        /// <param name="clienteModel"></param>
        public void Remover(int idCliente)
        {
            unitOfWork.RepositorioCliente.Remover(cliente => cliente.id_Cliente.Equals(idCliente));
            unitOfWork.Commit(shared);
        }


        /// <summary>
        /// Consulta padrão para retornar dados do cliente como model
        /// </summary>
        /// <returns></returns>
        private IQueryable<Cliente> GetQuery()
        {
            IQueryable<TB_CLIENTE> TB_CLIENTE = unitOfWork.RepositorioCliente.GetQueryable();
            var query = from cliente in TB_CLIENTE 
                        select new Cliente
                        {
                            Id_Cliente = cliente.id_Cliente,
                            Nome = cliente.nome,
                            Bairro = cliente.bairro,
                            Cidade = cliente.cidade,
                            Estado = cliente.estado,
                            Numero = cliente.numero,
                            Rua = cliente.rua,
                            Cep = cliente.cep,
                            Telefone = cliente.telefone,

                        };
            return query;
        }

        /// <summary>
        /// Obter todos as entidades cadastradas
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Cliente> ObterTodos()
        {
            return GetQuery();
        }

        /// <summary>
        /// Obtém um cliente
        /// </summary>
        /// <param name="idCliente">Identificador do cliente na base de dados</param>
        /// <returns>Cliente model</returns>
        public Cliente Obter(int idCliente)
        {
            IEnumerable<Cliente> clientes = GetQuery().Where(clienteModel => clienteModel.Id_Cliente.Equals(idCliente));
            return clientes.ElementAtOrDefault(0);
        }

        /// <summary>
        /// Atribui dados do Cliente Model para o Cliente Entity
        /// </summary>
        /// <param name="clienteModel">Objeto do modelo</param>
        /// <param name="clienteE">Entity mapeada da base de dados</param>
        private void Atribuir(Cliente ClienteModel, TB_CLIENTE clienteE)
        {
            clienteE.id_Cliente = ClienteModel.Id_Cliente;
            clienteE.nome = ClienteModel.Nome;
            clienteE.bairro = ClienteModel.Bairro;
            clienteE.cidade = ClienteModel.Cidade;
            clienteE.estado = ClienteModel.Estado;
            clienteE.numero = ClienteModel.Numero;
            clienteE.rua = ClienteModel.Rua;
            clienteE.cep = ClienteModel.Cep;
            clienteE.telefone = ClienteModel.Telefone;

        }
    }
}